#ifndef MULTIPLY_H
#define	MULTIPLY_H

#include "list.h"

template<typename Num, int value, int carry>
struct MultiplyByShort_
{
   typedef List<(Num::data * value + carry) % 10,
           typename MultiplyByShort_<typename Num::tail, value,
           (Num::data * value + carry) / 10 >::result > result;
};

template<int value, int carry>
struct MultiplyByShort_<EmptyList, value, carry>
{
   typedef List<carry % 10,
           typename MultiplyByShort_<EmptyList, value,
           carry / 10 >::result > result;
};

template<int value>
struct MultiplyByShort_<EmptyList, value, 0>
{
   typedef EmptyList result;
};

template<typename Num, int value>
struct MultiplyByShort
{
   typedef typename Reverse<typename MultiplyByShort_<
   typename Reverse<Num>::result, value, 0 >::result >::result result;
};

template<typename Num1, typename Num2>
struct Multiply_
{
   typedef typename Add_<typename Shift<
   typename MultiplyByShort_<Num1, Num2::data, 0 >::result,
           (Length<Num2>::length - 1)>::result, typename Multiply_<Num1,
           typename Num2::tail>::result, 0 >::result result;
};

template<typename Num1>
struct Multiply_<Num1, EmptyList>
{
   typedef EmptyList result;
};

template<typename Num2>
struct Multiply_<EmptyList, Num2>
{
   typedef EmptyList result;
};

template<typename Num1, typename Num2>
struct Multiply
{
   typedef typename Reverse<typename Multiply_<typename Reverse<Num1>::result,
           Num2>::result >::result result;
};

#endif

